import { Matrix4 } from "../utils/Matrix4";
import { WebGLUtil } from "../utils/WebGLUtil";
import { Render } from "./Render";
import { Webgl3DBase } from "./Webgl3Dbase";
import { IBufferInfo, WebglBase } from "./WebglBase";
/*
 * @Author: Snow
 * @Date: 2021-09-16 15:45:35
 * @Description: 
 */
export class Webgl3DCharF extends Webgl3DBase {

    public override initGLSL(): void {
        this.vsSource = `
            attribute vec4 aVertexPosition;
            attribute vec4 aVertexColor;
            uniform mat4 uViewMatrix;
            varying lowp vec4 vColor;
            void main() {
                gl_Position = uViewMatrix * aVertexPosition;
                vColor = aVertexColor;
            }
        `;

        this.fsSource = `
            varying lowp vec4 vColor;
            void main() {
                gl_FragColor = vColor;
            }
        `;
    }

    public override initUITools(): void {
        const gl = Render.GL;
        let translation = [200, 150];
        let angleInRadians = 0;
        let scale = [1, 1];

        // Setup a ui.
        const webglLessonsUI = (window as any).webglLessonsUI;
        webglLessonsUI.setupSlider("#x", { value: translation[0], slide: this.onUpateSlide(this, "x"), max: gl.canvas.width });
        webglLessonsUI.setupSlider("#y", { value: translation[1], slide: this.onUpateSlide(this, "y"), max: gl.canvas.height });
        webglLessonsUI.setupSlider("#z", { value: 0, slide: this.onUpateSlide(this, "z"), max: 5, min: -5, step: 0.01, precision: 2 });
        webglLessonsUI.setupSlider("#angle", { slide: this.onUpateSlide(this, "angle"), max: 360 });
        webglLessonsUI.setupSlider("#scaleX", { value: scale[0], slide: this.onUpateSlide(this, "scaleX"), min: -5, max: 5, step: 0.01, precision: 2 });
        webglLessonsUI.setupSlider("#scaleY", { value: scale[1], slide: this.onUpateSlide(this, "scaleY"), min: -5, max: 5, step: 0.01, precision: 2 });
        this.createSlider("scaleZ", { value: scale[1], slide: this.onUpateSlide(this, "scaleZ"), min: -5, max: 5, step: 0.01, precision: 2 })
        this.createSlider("rotationX", { value: 0, slide: this.onUpateSlide(this, "rotationX"), min: 0, max: 360, step: 1, precision: 0 })
        this.createSlider("rotationY", { value: 0, slide: this.onUpateSlide(this, "rotationY"), min: 0, max: 360, step: 1, precision: 0 })
        this.createSlider("rotationZ", { value: 0, slide: this.onUpateSlide(this, "rotationZ"), min: 0, max: 360, step: 1, precision: 0 })

        this.uiParam = { x: 0, y: 0, z: 0, rotationX: 0, rotationY: 0, rotationZ: 0, scaleX: 1, scaleY: 1, scaleZ: 1, anchorX: 0, anchorY: 0 };
    }

    public override initBuffer(): IBufferInfo {
        const gl = Render.GL;
        const vPos = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vPos);
        const vertices = [
            // left column front
          0,   0,  0,
          0, 150,  0,
          30,   0,  0,
          0, 150,  0,
          30, 150,  0,
          30,   0,  0,

          // top rung front
          30,   0,  0,
          30,  30,  0,
          100,   0,  0,
          30,  30,  0,
          100,  30,  0,
          100,   0,  0,

          // middle rung front
          30,  60,  0,
          30,  90,  0,
          67,  60,  0,
          30,  90,  0,
          67,  90,  0,
          67,  60,  0,

          // left column back
            0,   0,  30,
           30,   0,  30,
            0, 150,  30,
            0, 150,  30,
           30,   0,  30,
           30, 150,  30,

          // top rung back
           30,   0,  30,
          100,   0,  30,
           30,  30,  30,
           30,  30,  30,
          100,   0,  30,
          100,  30,  30,

          // middle rung back
           30,  60,  30,
           67,  60,  30,
           30,  90,  30,
           30,  90,  30,
           67,  60,  30,
           67,  90,  30,

          // top
            0,   0,   0,
          100,   0,   0,
          100,   0,  30,
            0,   0,   0,
          100,   0,  30,
            0,   0,  30,

          // top rung right
          100,   0,   0,
          100,  30,   0,
          100,  30,  30,
          100,   0,   0,
          100,  30,  30,
          100,   0,  30,

          // under top rung
          30,   30,   0,
          30,   30,  30,
          100,  30,  30,
          30,   30,   0,
          100,  30,  30,
          100,  30,   0,

          // between top rung and middle
          30,   30,   0,
          30,   60,  30,
          30,   30,  30,
          30,   30,   0,
          30,   60,   0,
          30,   60,  30,

          // top of middle rung
          30,   60,   0,
          67,   60,  30,
          30,   60,  30,
          30,   60,   0,
          67,   60,   0,
          67,   60,  30,

          // right of middle rung
          67,   60,   0,
          67,   90,  30,
          67,   60,  30,
          67,   60,   0,
          67,   90,   0,
          67,   90,  30,

          // bottom of middle rung.
          30,   90,   0,
          30,   90,  30,
          67,   90,  30,
          30,   90,   0,
          67,   90,  30,
          67,   90,   0,

          // right of bottom
          30,   90,   0,
          30,  150,  30,
          30,   90,  30,
          30,   90,   0,
          30,  150,   0,
          30,  150,  30,

          // bottom
          0,   150,   0,
          0,   150,  30,
          30,  150,  30,
          0,   150,   0,
          30,  150,  30,
          30,  150,   0,

          // left side
          0,   0,   0,
          0,   0,  30,
          0, 150,  30,
          0,   0,   0,
          0, 150,  30,
          0, 150,   0
        ];

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

        const vColorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vColorBuffer);
        const vColors = [
            // left column front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,

            // top rung front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,

            // middle rung front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,

            // left column back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,

            // top rung back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,

            // middle rung back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,

            // top
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,

            // top rung right
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,

            // under top rung
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,

            // between top rung and middle
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,

            // top of middle rung
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,

            // right of middle rung
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,

            // bottom of middle rung.
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,

            // right of bottom
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,

            // bottom
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,

            // left side
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220
        ];

        gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(vColors), gl.STATIC_DRAW);


        //顶点
        const indexs = [
            0, 1, 2, 3, 4, 5,
            6, 7, 8, 9, 10, 11,
            12, 13, 14, 15, 16, 17
        ];

        const indexsBuffer = gl.createBuffer();
        // gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexsBuffer);
        // gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexs), gl.STATIC_DRAW);

        this.bufferInfo = { vPos: vPos, vColor: vColorBuffer, indices: indexsBuffer };
        return this.bufferInfo;
    }

    public override draw(param?: any): void {
        const gl = Render.GL;
        WebGLUtil.resizeCanvasToMatchDisplaySize(gl);

        gl.clearColor(1.0, 1.0, 1.0, 1.0);
        //gl.enable(gl.CULL_FACE); //提出反三角形
        gl.enable(gl.DEPTH_TEST);
        //gl.clearDepth(1.0);
        //gl.enable(gl.DEPTH_TEST);
        //gl.depthFunc(gl.LEQUAL);
        // 清空画布和深度缓冲
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        //gl.clear(gl.COLOR_BUFFER_BIT);

        //this.updateMatrix();
        //上传顶点数据到shader
        {
            const numComponents = 3;  // pull out 3 values per iteration
            const type = gl.FLOAT;    // the data in the buffer is 32bit floats
            const normalize = false;  // don't normalize
            const stride = 0;         // how many bytes to get from one set of values to the next
            // 0 = use type and numComponents above
            const offset = 0;         // how many bytes inside the buffer to start from
            gl.enableVertexAttribArray(
                this.programInfo.attributes.aVertexPosition);
            gl.bindBuffer(gl.ARRAY_BUFFER, this.bufferInfo.vPos);
            gl.vertexAttribPointer(
                this.programInfo.attributes.aVertexPosition,
                numComponents,
                type,
                normalize,
                stride,
                offset);
            
        }

        //上传顶点颜色
        {
            let colorloc = gl.getAttribLocation(this.shaderProgram, "aVertexColor");

            gl.enableVertexAttribArray(
                colorloc);
            gl.bindBuffer(gl.ARRAY_BUFFER,this.bufferInfo.vColor);
            gl.vertexAttribPointer(
                colorloc,
                3,
                gl.UNSIGNED_BYTE,
                true,
                0,
                0);
        }

        

        ////上传顶点颜色
        // {
        // 	gl.enableVertexAttribArray(this.programInfo.attributes.aVertexColor);	
        // 	gl.bindBuffer(gl.ARRAY_BUFFER,this.bufferInfo.vColor);
        // 	gl.vertexAttribPointer(
        // 		this.programInfo.attributes.aVertexColor,
        // 		4,
        // 		gl.FLOAT,
        // 		false,
        // 		0,
        //         0);
        // }

        // Tell WebGL which indices to use to index the vertices
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufferInfo.indices);

        // Tell WebGL to use our program when drawing\
        gl.useProgram(this.shaderProgram);


        let x = this.uiParam["x"];
        let y = this.uiParam["y"];
        let z = this.uiParam["z"];
        let rotationX = this.uiParam["rotationX"];
        let rotationY = this.uiParam["rotationY"];
        let rotationZ = this.uiParam["rotationZ"];

        let scaleX = this.uiParam["scaleX"];
        let scaleY = this.uiParam["scaleY"];
        let scaleZ = this.uiParam["scaleZ"];

        let anchorX = this.uiParam["anchorX"];
        let anchorY = this.uiParam["anchorY"];

        let angleInRadiansX = rotationX * Math.PI / 180;

        let angleInRadiansY = rotationY * Math.PI / 180;

        let angleInRadiansZ = rotationZ * Math.PI / 180;


        let matrix: number[] = Matrix4.create();;

        let projectionMatrix: number[] = Matrix4.orthographic(0,gl.canvas.width, gl.canvas.height,0, -400,400);

        let translationMatrix: number[] = Matrix4.translation(x, y, z);

        let rotationXMatrix: number[] = Matrix4.rotateX(angleInRadiansX);

        let rotationYMatrix: number[] = Matrix4.rotateY(angleInRadiansY);

        let rotationZMatrix: number[] = Matrix4.rotateZ(angleInRadiansZ);

        let scalingMatrix: number[] = Matrix4.scaling(scaleX, scaleY, scaleZ);


        matrix = Matrix4.multiply(matrix, projectionMatrix);
        matrix = Matrix4.multiply(matrix, translationMatrix);
        matrix = Matrix4.multiply(matrix, rotationXMatrix);
        matrix = Matrix4.multiply(matrix, rotationYMatrix);
        matrix = Matrix4.multiply(matrix, rotationZMatrix);
        matrix = Matrix4.multiply(matrix, scalingMatrix);


        gl.uniformMatrix4fv(
            this.programInfo.uniforms.uViewMatrix,
            false,
            new Float32Array(matrix));
        // gl.uniformMatrix4fv(
        // 	this.programInfo.uniforms.uModelViewMatrix,
        // 	false,
        // 	this.modelViewMatrix);
        // gl.uniformMatrix4fv(
        //         this.programInfo.uniforms.uViewMatrix,
        //         false,
        //         this.viewMatrix);

        //gl.drawElements(gl.TRIANGLES,18,gl.UNSIGNED_SHORT,0);
        gl.drawArrays(gl.TRIANGLES, 0, 96);
    }
}